{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Textbook and Shor's algorithms\n",
    "\n",
    "Qiskit contains implementations of the well known textbook quantum algorithms such as the [Deutsch-Jozsa algorithm](https://qiskit.org/textbook/ch-algorithms/deutsch-jozsa.html), the [Bernstein-Vazirani algorithm](https://qiskit.org/textbook/ch-algorithms/bernstein-vazirani.html) and [Simon's algorithm](https://qiskit.org/textbook/ch-algorithms/simon.html).\n",
    "\n",
    "Qiskit also has an implementation of [Shor's algorithm](https://qiskit.org/textbook/ch-algorithms/shor.html).\n",
    "\n",
    "The preceding references have detailed explanations and build-out of circuits whereas this notebook has examples with the pre-built algorithms in Qiskit that you can use for experimentation and education purposes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "import numpy as np\n",
    "from qiskit import BasicAer\n",
    "from qiskit.aqua import QuantumInstance\n",
    "from qiskit.aqua.algorithms import BernsteinVazirani, DeutschJozsa, Simon, Shor\n",
    "from qiskit.aqua.components.oracles import TruthTableOracle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Deutsch-Jozsa algorithm\n",
    "\n",
    "Lets start with the [Deutsch-Jozsa algorithm](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.DeutschJozsa.html) which can determine if a function is `'balanced'` or `'constant'` given such a function as input. We can experiment with it in Qiskit using an oracles created from a truth tables. So for example, we can create a `TruthTableOracle` instance as follows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "bitstr = '11110000'\n",
    "oracle = TruthTableOracle(bitstr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As shown, the truthtable is specified with the `bitstr` containing values of all entries in the table. It has length $8$, so the corresponding truth table is of $3$ input bits. We can of course see that this truth table represents a `'balanced'` function as half of values are $1$ and the other half $0$.\n",
    "\n",
    "It might seem like a moot point running Deutsch-Jozsa on a truthtable as the function outputs are literally listed as the truthtable's values. The intention is to create an oracle circuit whose groundtruth information is readily available to us but obviously not to the quantum Deutsch-Jozsa algorithm that is to act upon the oracle circuit. In more realistic situations, the oracle circuit would be provided as a blackbox to the algorithm.\n",
    "\n",
    "Above said, we can inspect the circuit corresponding to the function encoded in the `TruthTableOracle` instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "tags": [
     "nbsphinx-thumbnail"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAncAAAEKCAYAAABwnnPgAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzt3Xt8FPW9//H37ObGJZEoQuQS7kHBEBRPbQMVKCL1QB/SHj14HtYfCqX4sJ7WtihIWx/l0EePrdC7Feq11AvtqdJapXgrESKVolyUgNwS7iQQwiXcctmd3x8DhHDZ3SS7OzPfvJ6PxzxkZyezH7/5ZOa9M7Ozlm3btgAAAGCEgNsFAAAAIH4IdwAAAAYh3AEAABiEcAcAAGAQwh0AAIBBCHcAAAAGIdwBAAAYhHAHAABgEMIdAACAQQh3AAAABiHcAQAAGIRwBwAAYBDCHQAAgEEIdwAAAAYh3AEAABiEcAcAAGAQwh0AAIBBCHcAAAAGIdwBAAAYhHAHAABgEMIdAACAQQh3AAAABiHcAQAAGIRwBwAAYBDCHQAAgEEIdwAAAAYh3AEAABiEcAcAAGAQwh0AAIBBUtwuAACa47ubNmhddXXSX7cgM1Nz+w9I+uuiafzYH27VLLW+vjZ9rAl3AHxpXXW1lh2qcrsMeJQf+8OPNfuV6WPNaVkAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAgxDuAAAADEK4AwAAMAjhDgAAwCCEOwAAAIP44hsqRo0apcOHD+ujjz5qNP/gwYPq27evpk6dqscee8yl6sxTe0La87G0d71Ue1xKzZByBkrdCqSMTLerg9tsW9q/Wdq1VqqukCxLuqKn1O06Kbub29XBC44dkHatkfZvkcL1UttsqdtgKWeAFPTFXgeJVHdK2vuJtOcTqaZaSkmXcq5xeqTNZW5XZwZfHLkbNGiQNm7cqHA43Gj+rFmzlJaWppkzZ7pUmXlOHJJWLpC2FUsnD0uhOulUtbT9A+mD56Wj5W5XCDeFw9Inf3Omw7ulUK1UXyNVbJY+WiiVrXS7wouz6+pUd98DCs1/qtH80KK/qO6rE2UfO+ZSZeYp/1T6YIHzBrHupLMNqT4gbXxL+uiPTr94kR97xI81nzoqrfyDtOU96USV0x81x6Qdq5x9zKHdbld4cX4ba9+Eu5MnT6q0tPTsvC1btmjevHmaNWuWsrKyXKzOHHZYWvuqVHP84s/X10prXnH+GNE6bf/AOWonSbLPeeL0v7ctlyq3Jbuq6KzUVKXMeEjh1xcrvGatJMkuK1P42d8r+PA0We3bu1yhGY5VSuvfUOPeUMPjo/ukjW8nu6rY+LFH/FazbUvr/uoEvIsJ1Tv7oLpTya0rFn4ba9+EO0kqKSk5O2/69Onq16+fpkyZIknavn27hg8frry8POXn52v58uWu1OpnB7c7R+4u2DCfYTvvxCs+TWJR8IxwvbRrdZSFLGnHR1GWcYnVs4cCkyYqNOfnsquqVP/Y4wrc9iUFBuW7XZoxdq/Vpbcfp1Vscs4GeJEfe8RPNR/Z61zKEWkfE6qV9pVc4nmX+WmsfRHuBg4cqGAweDbcFRcXa9GiRZozZ46CwaAkaerUqZowYYI2b96s+fPn684771RtbW3Mr2FZVquf/mfabxUOhyKOUyhcr9/NedX1WpmSPw3qNyz6O2pbOrRTSk9tk/B6ioqKYv77PiMw/jZZud1VP/UbUjCowMS7m7yOoqIi138XXp3WvBfDOTVbGj9qkif7Q2p5j7SkP9yquaV1xzp9d8r/yrbDEesIh8P64+/eNbY/mjPWzaqzWT+VZBkZGcrLy9P69eslSdOmTdPo0aN16623SpIqKytVXFysyZMnS5IKCwvVpUsXLV261LWa/SgtJUO2HflttyVLaSkZSaoIXpKWGvvvPTUlPYGVNJ9lWbIG5UtHjigw6guyUlPdLskosW4bvLwN8WOP+KXmWPYxgUCgSduaZPPLWPsi3EnOqdmSkhItXLhQq1at0ty5c88+t3PnTnXu3Fnp6Q07lF69emnHjh0xr9+27VY/PfDdSQpG+ShbIBDU7V/9d9drZUr+tOLDd2L6W0ptI1WfOJzwekaMGBHz3/fZv/OyMoVfWqjAhDsUfuEl2fv3N3kdI0aMcP134dUpN6+jFMOBhudf/q0n+0NqeY+0pD/cqrmldcc6fW/2txUIBCMXYkmjxw01tj+aM9bN4atwt2nTJj3yyCOaNGmS8vO9d47b7666VrJi6IiuBYmvBd6TkSVd0UtRd97dBju3R/Eau7bOuUbmK+MVnHyvrKGfU+jxn8kORz5NhNh1K1Dka+4s51YX2bnJqqhp/Ngjfqo552opEO1WOLZ39zF+GmvfhLuCggLV1NSosrJSs2fPbvRcbm6uKioqVFPT8Bn7srIy9ejRI9ll+lp6O6nPsMjL5A6R2l2enHrgPf2Gn75P2SXCW9tsp0e8KPzsc7JSUhS4+y5JUvD++2SXVyj8yiKXKzNH5/5SdvfIy1x9szfDv+TPHvFTzSnpUt7IyMt0yZcuuyo59TSVn8baN+Fu7Nixsm1b1dXVysnJafRcx44dNXToUD3zzDOSpBUrVmjPnj0aOTJKF+ECPT/jbHxT2zSeH0yT+nxe6jfClbLgEe07Sjf8l5TV+cLnruwr3XCnc9NrrwmvWavw4iUKznhYVopz6MBq21bB6dMUXvCC7LIylys0QyAoDf6K1HXQhWcB2mZL1/3H6aO/HuTHHvFjzd0KpAG3SmntGs8Ppkq9PitdM9qduqLx21hbdnNP6HpMaWmp7rnnHpWXlystLU1PPPGEhg8f7nZZvhUOObdGWXf6DcnIbzl/fMAZRyukf/3B+ffQKcm/s/zNH67UskNVyX1RSTdlX653brgx6a/rN7UnpGW/df49ZILUoVtyj9j5sT/cqllKfl+Hw1LVDmntK87jEd+UUtKS9vLGj7UxXwTTu3dvLVu2zO0yjBEISlf2aXhMsMP5zj16x1cG4XxpbRv+He1ULVqfQEDqeM5R3GQGu9bAN6dlAQAAEB3hDgAAwCCEOwAAAIMQ7gAAAAxCuAMAADAI4Q4AAMAghDsAAACDEO4AAAAMYsxNjAG0LgWZma3qddE0fuwPN3urtfW16WNNuAPgS3P7D3C7BHiYH/vDjzX7leljzWlZAAAAgxDuAAAADEK4AwAAMAjhDgAAwCCEOwAAAIMQ7gAAAAxCuAMAADAI4Q4AAMAghDsAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAg6S4XQBwMd/dtEHrqqtdee2CzEzN7T/AlddG7NzqEfrDH+gPRGL6PoZwB09aV12tZYeq3C4DHkaPIBL6A5GY3h+clgUAADAI4Q4AAMAghDsAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAgxDuAAAADOKbcDdq1CgNGTLkgvkHDx5Udna2ZsyY4UJV5qo7Je1e1/C45rh7tcB77LBUWdrw+Mg+92qBNx0/5/6w5Z9K4Xr3aoH31NdIez5peHzKnS+LMJZvwt2gQYO0ceNGhcPhRvNnzZqltLQ0zZw506XKzGLb0rZiafmT0qdvN8wvni9telcKh9yrLRK7rk519z2g0PynGs0PLfqL6r46UfaxYy5VZp6qnVLxU9LaVxvmrXpRWvkH6cRh9+qKhP5IntqT0ppXpX8+2zBv/evSsnnSvg3u1RUNPZIcti1tXykte1La+GbD/OLfSSVLpJBH3wT4rT98Fe5Onjyp0tKGwwVbtmzRvHnzNGvWLGVlZblYnTm2LpPKPrgwxNlhadcaacObF/85t1mpqUqZ8ZDCry9WeM1aSZJdVqbws79X8OFpstq3d7lCMxzeK635s1Rzke1Y9X7pw5cv/pzb6I/kCNVJq/8kHSy98Ln6U1LJYuconhfRI8mxfaW0dflFjuTa0r710id/cwKg1/itP3wV7iSppKTk7Lzp06erX79+mjJliiTp0UcfVV5engKBgP785z+7UqefnToq7VgVeZnyDdLRiuTU01RWzx4KTJqo0Jyfy66qUv1jjytw25cUGJTvdmnG2Lrs9Ib3YhtfW6o9Lu34MNlVxYb+SLx9G6RjByIvs3mpdN4JGM+gRxKr9oRUuiLyMpXbpEO7klNPU/mpP3wT7gYOHKhgMHg23BUXF2vRokWaM2eOgsGgJOmLX/yilixZoptuusnNUn1r7/oYFrKkvR8nvJRmC4y/TVZud9VP/YYUDCow8W63SzLGiUPS4d26eLA7x95PnCO9XkR/JNaejyVZkZepPS5VlSWlnGahRxKnfGMM2wbL2YZ4lV/6wzfhLiMjQ3l5eVq/3kkg06ZN0+jRo3XrrbeeXaawsFC9e/du1voty2r105O/fE6hKBc8hEMhvbpwccJrKSoqav7vcVC+dOSIAqO+ICs1tcnrKCoqcv134cXp8zeOjmn86mukzHYdPNkj9Edipz2lB6OGf0ma/P++4cn+kFreI/THpafH/ucXCkW7cNuW3v37CmP7ozk90hy+CXeSc2q2pKRECxcu1KpVqzR37ly3SzLKiZrqqI1ky9bJWg9eVHWaXVam8EsLFZhwh8IvvCR7/363SzLGyZrYPs4WDodUW3cywdU0D/2RWCdqqmXHcMHUiRh7yQ30SOKcqKlWIMo+JhwOxbytcYNf+sN34W7Tpk165JFHNGnSJOXnx+88t23brX6a/atvKhAIRhynYCBFD3zvPxNey4gRI5r+O6ytc66B+Mp4BSffK2vo5xR6/Geym3iBz4gRI1z/XXhxWl/2gdKjXTNsSZ36BVVbX+O5HqE/Ej/deEvPqG8QrYD0xrIFnuuPePUI/XHp6dcLfiDLihw7AoGg7v7vMcb2R3N6pDl8Fe4KCgpUU1OjyspKzZ492+1yjJPdXcrsrEtfM2NJGVnSlf2SWVXsws8+JyslRYG775IkBe+/T3Z5hcKvLHK5MjMEAlKPf4uykC31uCEp5TQZ/ZF43QZLgaAiXnfXNV9Ka5u0kpqEHkmszE5Sdm6EBSynN3KuTlpJTeKn/vBVuBs7dqxs21Z1dbVycnLcLsc4liUN/rLUNvvMjMbPp7eXrr/j9MbbY8Jr1iq8eImCMx6WlZIiSbLatlVw+jSFF7wgu8zDV3D7SPfrpe7XnX5w/g7ckq4Z47xJ8Br6IznadJAKvnyRbcTpXunYW8obmfSyYkKPJEf+l5yQJ+mCbUhaG2cfE0xLellR+a0/LLu5x/w86Ac/+IGee+45HThwQO3bt1ebNm303nvvqU+fPm6X5iuhOqlik/Pp2cO7nXn9R0lXDZBS0pNTw80frtSyQ1XRF0yAm7Iv1zs33OjKa/uBbUtH9jjfYFK+0ZnXfYjUrUBqd3ny6nCrR+iP6GqOOZ+cPXPbi459pG6DpCt6Oadlk4H+8K5wvbR/i/MNFYd2OvPyRkpXDZRSM5JTg+n7GF8duYtm9uzZ2r17t2pqanTw4EHt3r2bYNcMwVSpy7XSDXc2zOt+XfKCHbzNsqQO3aRrxzbM6z8yucEO3pbeXupd2PB48JedgJesYAdvC6RIOddIQ/6zYV7ukOQFu9aAPzUAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAgxDuAAAADEK4AwAAMAjhDgAAwCApbhcAXExBZmarfG3Ezq3fE/3hD/QHIjF9H0O4gyfN7T/A7RLgcfQIIqE/EInp/cFpWQAAAIMQ7gAAAAxCuAMAADAI4Q4AAMAghDsAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAgxDuAAAADEK4AwAAMAjhDgAAwCCEOwAAAIOkuF2An3x30watq6525bULMjM1t/8AV17bDX4da7fqbm39IflzrP3a135EfzQN/ZE8yRhrwl0TrKuu1rJDVW6X0Sr4daz9Wrcf+XGs/VizX/lxrP1Ys1+ZPtaclgUAADAI4Q4AAMAghDsAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAgxDuAAAADEK4wyXZttsVADAB2xJcDH2ROL4Jd6NGjdKQIUMumH/w4EFlZ2drxowZLlQVmV1Xp7r7HlBo/lON5ocW/UV1X50o+9gxlyqL7ORh6dN3paJfNczbsEQ6VuleTdH4caz9WLMkheulnaulFc80zFv1slSxybsba7+OtV/rrtoprX214fHyeVLpCqnulHs1RePHsfZjzZJ0qlravFR679cN89Yvlo5WuFdTNH4ba9+Eu0GDBmnjxo0Kh8ON5s+aNUtpaWmaOXOmS5VdmpWaqpQZDyn8+mKF16yVJNllZQo/+3sFH54mq317lyu80NFy6YMF0u41UqiuYf7e9dK//iBV7XCvtkj8ONZ+rDlUJ61+Rdr8D+nEoYb5R/ZKn/zNme/FgOfHsZb8WffO1dLqP0mVZQ3zao874W7Vi1LNcfdqi8SPY+3Hmo9VSisXSDs/kuprG+aXb3T648BW92qLxG9j7atwd/LkSZWWlp6dt2XLFs2bN0+zZs1SVlaWi9VdmtWzhwKTJio05+eyq6pU/9jjCtz2JQUG5btd2gXCIWndXxqHukbPh6V1f5Xqa5JbV6z8NNZn+K3mbe9Lh3dd5InTgW7XGucInhf5bazP8FPdR8udgC/pbE+c68QhaeObSS2pSfw01mf4qWbblj7+6yWO4NqSHXbeJHr2DYCPxtpX4U6SSkpKzs6bPn26+vXrpylTpujQoUMaN26c8vLyVFBQoFtuuUVbt3rjLUBg/G2ycrurfuo3pGBQgYl3u13SRR3YKtUc00U3ypIzP1Qr7duQzKqaxi9jfS6/1Byqlfasi7KQ5bwj9yq/jPX5/FL3rjWSrMjLVJZKJw4npZxm8ctYn8svNVftOH3EP8LR/XBI2vtJ0kpqMr+MtW/C3cCBAxUMBs+Gu+LiYi1atEhz5sxRMBiUZVl68MEHtXnzZq1bt07jxo3TvffeG/P6LcuKOhUVFTWrdsuyZA3Kl44cUWDUF2SlpjZ5HUVFRTHV2JLpf783X6FwKGIdoXBIz/7yLwmvxa9j3Zy63a451un6a4Zf8qjuWbZ0dJ+UkdbWkz3i9lj7ta9jnUr+uS/ijvuM28dM8WR/SC0fa/rj0tOMB36qsB2OWEfYDuuV55ca2x/NGevm8E24y8jIUF5entavXy9JmjZtmkaPHq1bb71VktShQwfdfPPNZ5cvLCxUWVnZRdeVbHZZmcIvLVRgwh0Kv/CS7P373S7pooKBlKgXTFmSUoJNb+Zk8ctYn8svNQcDKbEv69Ee8ctYn88vdcfaI8Fg7L2UbH4Z63P5pebY9jEW+5g48E24k5xTsyUlJVq4cKFWrVqluXPnXnLZX/ziFxo/fnzM67ZtO+o0YsSIJtds19Y55+W/Ml7ByffKGvo5hR7/mexw5Hcv5xsxYkRMNbZk+taMyVE3uoFAUBPuGZvwWvw61k2t2ws1xzr9c827UU+5SVJ6pnTsxBHP9YgXxtqvfR3r1GvglTH1yB/+70nP9Ue8xpr+uPT06I+/o0AgGLEOy7L0xS8PM7Y/mjPWzeG7cLdp0yY98sgjmjRpkvLzL34R46xZs7R161b99Kc/TXKFFwo/+5yslBQF7r5LkhS8/z7Z5RUKv7LI5coudNUAKcrfnSSp66DE19IcfhrrM/xUc3p7qVM/Rd15dx8sNfNMQkL5aazP5ae6uw1W5NOyltSuo3RZl2RV1DR+Gusz/FRz5/5SSnr05boVJL6W5vDTWPsq3BUUFKimpkaVlZWaPXv2RZf50Y9+pNdff11LlixR27Ztk1xhY+E1axVevETBGQ/LSnGOiFlt2yo4fZrCC16Q7ZHTxmekZkhXj468TN+bpDaXJaeepvDbWEv+rLnfcCmtjS4Z8LJypO7XJ7WkmPhxrCX/1X1lX6lT3iWetKRAQBowxqPh32djLfmv5mCqdM2Y0w8u0QM9b5TaX5m0kmLmt7G27OYe8/OgWbNmafHixXrzzTfVoUOHuK//5g9XatmhqrivNxY3ZV+ud264MSmvtX+LtHW5dOKc/9WMLKl3odTl2qSU4NuxdqvuZPbHySPODUjPvR9VIOj0Rt/hUkpaUsrw5Vj7ta+bIhyWyv4p7Vrd+LZJHbpLecOdNwDJQH80TTK3IZVl0tZl0rEDDfPS2zvBrluSjvybPtbevaq1iUpKSvTDH/5Qffr0aXQufe3ate4V5VOd+jnvwKsrpH+94MwbOsWb77aRfG0ukwrGO3eZL57vzLvp/thOt8B8gYDUZ6izo176C2fe5yZJ7S53ty54R8de0hU9nXC3coEzb9jXJctX5xK9zZhwN3DgwGZfeIgLWVbjd9gEO5wvI7Ph3wQ7nO/cz2YR7HA+y5IyO53zmGAXVwwnAACAQQh3AAAABiHcAQAAGIRwBwAAYBDCHQAAgEEIdwAAAAYh3AEAABiEcAcAAGAQY25inAwFmZnRFzLwtd3g17F2q+7W1h+SP8far33tR/SHf17bDaaPtVHfLYv4e2eO89+bp7lbB7yJ/kAk9AeioUcSg9OyAAAABiHcAQAAGIRwBwAAYBDCHQAAgEEIdwAAAAYh3AEAABiEcAcAAGAQwh0AAIBBCHcAAAAGIdwBAAAYhHAHAABgEMIdAACAQQh3AAAABiHcAQAAGIRwBwAAYBDCHQAAgEEIdwAAAAZJcbsAeEt9rVRZKh0tl45XNszf9A8pq7PUsY+UmuFefXCXbUuH90iHd0vV+xvmr1/s9MflPaT2Hd2rD+47eUQ6WCYdrWiYt3aRlHmldFkX6fKeUoDDCq1WqE6qLJOO7pOOnbOP+fQdKStH6thbSmvrXn2msGzbtt0uAu6rPSGV/VPaWyKFai+9XCBFyrlG6l0oZWQmrz64y7alveulHaukE1WRl+3QTer1WemKnkkpDR5xtEIqXSFVbou8XHp7qft1Uu4QZ3uC1qG+xtnH7Fkv1Z+69HJWUOrcX+pTKLXpkLz6TEO4gw5slTa8JdWdiP1nUtKlvC9IXQYmri54w6mjUsnfpUO7mvZzXa51eiQlLTF1wRvCYalshVS2UlIT9ibtOkrX/ruU2SlhpcEjDm6XNiyRao7F/jPBVKnfcKlrgWRZCSvNWIS7Vm73WudweHP1LnQmmOl4lbT6T03bKJ8rK0e67nZO5ZsqHJI+eV06sKV5Px9MlQZ/RcruHt+64B37NjhvDpsS/M+VO0TqN4KA11Rc+dCK7d/SsmAnOadhdq+LTz3wlrqT0ur/a36wk5xrNz/+q2SH41cXvGPTu80PdpJz/dXaV6XjB+NXE7yjakfLgp0k7fzIuRwETUO4a6VqT0gb34q+3M3TnCmSLUXSicNxKQsesukfUk115GVi6Y9Du6Rda+JXF7yhslTa83HkZWLpj1Cdc8qONwBmqa+RSpYoarCLpUe2FUvHDsSttFbBN+HOtm3NmzdP119/vdq2bavc3Fw9+OCDOnasBYcVWrHS950jM/EQqpO2vBefdcEbDu+WyjfGb31bl8ev3+A+O+wctYuXI/ukfSXxWx/ct31l9DeHsbLD0ual8VlXa+GLcBcOh3XXXXdp2rRpuuOOO/TGG29o5syZev755zV58mS3y/Od+hrnOoh4OrBVOhWnP2S4b9fa+K4vXO98EhtmqCxzbnkST7vWOp/Khv+F6qU9n8R3nVU7OX3fFL74IPoTTzyhP/7xjyoqKtLnP/95SdLIkSN14MABPfroo5o/f746dOAz07E6sNU52hZXtlTxqdTj3+K8XiRdqE7avzn+6923QepxQ/zXi+Qrj/ObQ0mqrnBus9PuivivG8lVtT0xR+rLN0p9hsV/vSbyxZG7uXPnaty4cWeD3Rl9+/aVJO3evVvbt2/X8OHDlZeXp/z8fC1fvtyNUn3hSHli1ns0QetFch07kJjrn44fSMCbCrgiUX/rido2IbnYx7jP8+Fu27Zt2rFjh8aOHXvBc7t2OTfe6tKli6ZOnaoJEyZo8+bNmj9/vu68807V1ka4G28rdu43T8QTF7ya4ViC+sO2nVurwN9CtfE/JXvGcbYhRkjYPiZB6zWR50/LHjjg/LV36dLlgufefvttDR48WOFwWMXFxXrttdckSYWFherSpYuWLl2qMWPGxPQ6Viu6ic6v/3ulrs79TKN50T6tdLHn35nT+HHpth0qtHq2qDa478vDvqn7b/tlo3nN6Q/pwh4p/OxQlWxf0YLq4LbL2nXUn3/YOIXFqz9+/avf6tcjv9GC6uAFj015S0PyRjeaF48eOXjgsCwru4XV+U9zbkfs+XDXs2dPSdLWrVsbzV+8eLHeeecdLViwQDt37lTnzp2Vnp5+9vlevXppx44dySzVN+rqa3y1XiRXIn+P9Ij/0R+Ihn2M+zwf7nJycjRu3Dj9+Mc/VlZWlnr37q1ly5bpJz/5iaZOnaq7775bq1evbvHrtKYv6tjwprT3vE8ynf8O+owz76Yu9fy5Bn82r1WNo6mqdjrfSnGuePSHJJVs/VAp6dGXg7cte1KqPd7wOF798b3Z39aTr327ZcXBdZuLpJ0fNp4Xjx7pdU1n9jEx8ny4k6QFCxbo4Ycf1ve//30dOXJEAwYM0G9+8xvde++9kqTc3FxVVFSopqbm7NG7srIy9ejRw82yPSsr58JwF5f1do7/OpF8ifo9ts0Wwc4QWTlS5bYErJdtiBGychK0XvojZr4Id9nZ2Xrqqacu+XzHjh01dOhQPfPMM7r//vu1YsUK7dmzRyNHjkxilf5xZV/nBqTx/kRkp7z4rg/uSEmXrujpfNl3PHXuH9/1wT2d8+If7tp0kDLZeRuhYy8pkOLc3zKe2IbEzvOflo3VvHnztHDhQuXl5enrX/+6Xn75ZaWlpbldlielt5M69YvvOjt0k9p3jO864Z5ug+O8QkvqOijO64RrOvWXUjPiu85uBXw5vClS0qWrBsR3ne07SVlXxXedJvPFkbtYnLkWD7HpM0w6sC1O76wsKW9EHNYDz+jYR8ru7nwvbDz0GCJlZMVnXXBfMEXqe1Ns308dizYdEvCGAq7q9TmpYpPzjUjxkDeC8N8Uls3Via3WztXS5n+0fD09Pyv15a7hxjl5WPpggXNfs5Zod7n0mbulYGp86oI32La38Q5GAAAFUklEQVS09pU4nL63pCETpOxu8agKXrKvRCr5e8vX0+066epRLV9Pa2LMaVk0XffrpNwhLVtHzgCpz9D41ANvadNBKhjvXDvTXBmZ0uD/INiZyLKk/C+18CJ3Sxr4RYKdqa4aKPUubNk6ruzLmaHm4MhdK2fbzkfWty5v4gcsLKnnZ5xgZ/EWwWhH9knr33CO5DVFh27StWOdgAdz1dc4t1dq6vcRp7aRBoxxdt4w2+61zu1RmnoZUPfrpX7DpUAwIWUZjXAHSc7Xumwucr7wOZrLujrvpC7j4tZWI1Qrla6Qdq+L/v2w6e2lHp9xjgxzjUzrUfGptO196cShyMtZQSnnaqnfTVJau+TUBvedOOTsY2L5lHVWjhPqsrsnvCxjEe7QyPEqZyN9tNwJfKeOOvOv6OncpqBzfymzk6slwkX1tU5/HN4tHa2Qjh905mflOP1xeQ/pyj68026tbNu5CXZlqVRd4fSJ5NzjMPP0px2vuoZQ15qdPCyVn9nHHGj4nuLLezjbkE79OHAQD4Q7RHTmruHRvhcQrRP9gUjoD0RDjyQGV0sBAAAYhHAHAABgEMIdAACAQQh3AAAABiHcAQAAGIRwBwAAYBDCHQAAgEEIdwAAAAYh3AEAABiEcAcAAGAQwh0AAIBBCHcAAAAGIdwBAAAYhHAHAABgEMIdAACAQQh3AAAABiHcAQAAGIRwBwAAYBDCHQAAgEEIdwAAAAYh3AEAABiEcAcAAGAQwh0AAIBBCHcAAAAGIdwBAAAYhHAHAABgEMIdAACAQQh3AAAABvFNuCsqKtL48ePVvXt3ZWRkqGvXrvra176mI0eOuF0aAACAZ6S4XUCs1q1bp2HDhmnKlCnKzMzUxo0b9f3vf1+S9PTTT7tcHQAAgDf4Jtx961vfOvvvcDiswsJCrVu3Tu+++66LVQEAAHiLL07LhkIhvfjiixo2bJg6d+6sYDCo1NRUPfnkk2rfvr0kafv27Ro+fLjy8vKUn5+v5cuXu1w1AABA8vniyN3EiRP16quv6oEHHtD06dPVsWNHpaSkaNSoUcrPz5ckTZ06VRMmTND999+vFStW6I477lBZWZnS0tJieg3LshL5v+Bbbz9uS2J8cHH0ByKhPxANPRKdbdtN/hnPh7v169frxRdf1NNPP63Jkyefnf/++++rurpaQ4YMUWVlpYqLi/Xaa69JkgoLC9WlSxctXbpUY8aMcat0AACApPN8uNu5c6ck6eqrrz47r66uTt/5znckSUOGDNHOnTvVuXNnpaenn12mV69e2rFjR8yv05xk3JrY0xgfXBr9gUjoD0RDj8SX56+5KygoUEZGhmbMmKG33npLL7/8sgoLC3Xw4EEFg0ENHjzY7RIBAAA8w/PhrmvXrnrppZdUXl6u2267TXPnztVDDz2kwsJC9e/fX23btlVubq4qKipUU1Nz9ufKysrUo0cPFysHAABIPss25HzkLbfcovHjx5/9QMXtt9+u7du3x/yBCgAAABMYE+5KS0t1zz33qLy8XGlpaXriiSc0fPhwt8sCAABIKmPCHQAAAHxwzR0AAABiR7gDAAAwCOEOAADAIIQ7AAAAgxDuAAAADEK4AwAAMAjhDgAAwCCEOwAAAIMQ7gAAAAxCuAMAADAI4Q4AAMAghDsAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAgxDuAAAADEK4AwAAMAjhDgAAwCCEOwAAAIMQ7gAAAAxCuAMAADAI4Q4AAMAghDsAAACDEO4AAAAMQrgDAAAwCOEOAADAIIQ7AAAAgxDuAAAADEK4AwAAMAjhDgAAwCD/Hxla/qyp6A+mAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9a07bd0e80>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "oracle.circuit.draw(output='mpl')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As seen, the $v_i$'s correspond to the 3 input bits; the $o_0$ is the oracle's output qubit; the $a_0$ is an ancilla qubit.\n",
    "\n",
    "Next we can simply create a `DeutschJozsa` instance using the oracle, and run it to check the result."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The truth table 11110000 represents a 'balanced' function.\n"
     ]
    }
   ],
   "source": [
    "dj = DeutschJozsa(oracle)\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "result = dj.run(QuantumInstance(backend, shots=1024))\n",
    "print(f'The truth table {bitstr} represents a \\'{result[\"result\"]}\\' function.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can of course quickly put together another example for a `'constant'` function, as follows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The truth table 1111111111111111 represents a 'constant' function.\n"
     ]
    }
   ],
   "source": [
    "bitstr = '1' * 16\n",
    "oracle = TruthTableOracle(bitstr)\n",
    "dj = DeutschJozsa(oracle)\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "result = dj.run(QuantumInstance(backend, shots=1024))\n",
    "print(f'The truth table {bitstr} represents a \\'{result[\"result\"]}\\' function.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bernstein-Vazirani algorithm\n",
    "\n",
    "Next the [Bernstein-Vazirani algorithm](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.BernsteinVazirani.html) which tries to find a hidden string. Again, for the example, we create a TruthTableOracle instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "bitstr = '00111100'\n",
    "oracle = TruthTableOracle(bitstr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As shown, the truthtable is specified with the `bitstr` containing values of all entries in the table. It has length $8$, so the corresponding truth table is of $3$ input bits. The truthtable represents the function mappings as follows:\n",
    "\n",
    "- $\\mathbf{a} \\cdot 000 \\mod 2 = 0$\n",
    "- $\\mathbf{a} \\cdot 001 \\mod 2 = 0$\n",
    "- $\\mathbf{a} \\cdot 010 \\mod 2 = 1$\n",
    "- $\\mathbf{a} \\cdot 011 \\mod 2 = 1$\n",
    "- $\\mathbf{a} \\cdot 100 \\mod 2 = 1$\n",
    "- $\\mathbf{a} \\cdot 101 \\mod 2 = 1$\n",
    "- $\\mathbf{a} \\cdot 110 \\mod 2 = 0$\n",
    "- $\\mathbf{a} \\cdot 111 \\mod 2 = 0$\n",
    "\n",
    "And obviously the goal is to find the bitstring $\\mathbf{a}$ that satisfies all the inner product equations.\n",
    "\n",
    "Lets again look at the oracle circuit, that now corresponds to the binary function encoded in the `TruthTableOracle` instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f9a07842978>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "oracle.circuit.draw(output='mpl')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Again the $v_i$'s correspond to the 3 input bits; the $o_0$ is the oracle's output qubit; the $a_0$ is an ancilla qubit.\n",
    "\n",
    "Let us first compute the groundtruth $\\mathbf{a}$ classically:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The groundtruth result bitstring is 110.\n"
     ]
    }
   ],
   "source": [
    "a_bitstr = \"\"\n",
    "num_bits = math.log2(len(bitstr))\n",
    "for i in reversed(range(3)):\n",
    "    bit = bitstr[2 ** i]\n",
    "    a_bitstr += bit\n",
    "print(f'The groundtruth result bitstring is {a_bitstr}.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we can create a `BernsteinVazirani` instance using the oracle, and run it to check the result against the groundtruth."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The result bitstring computed using Bernstein-Vazirani is 110.\n"
     ]
    }
   ],
   "source": [
    "bv = BernsteinVazirani(oracle)\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "result = bv.run(QuantumInstance(backend, shots=1024))\n",
    "print(f'The result bitstring computed using Bernstein-Vazirani is {result[\"result\"]}.')\n",
    "assert(result['result'] == a_bitstr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simon's algorithm\n",
    "\n",
    "[Simon's algorithm](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.Simon.html) is used to solve [Simon's problem](https://en.wikipedia.org/wiki/Simon's_problem). Once again, for the example, we create a TruthTableOracle instance, where the construction shows a different form."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "bitmaps = [\n",
    "    '01101001', \n",
    "    '10011001', \n",
    "    '01100110'\n",
    "]\n",
    "oracle = TruthTableOracle(bitmaps)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As shown, the truthtable is specified with three length-8 bitstrings, each containing the values of all entries for a particular output column in the table. Each bitstring has length $8$, so the truthtable has $3$ input bits; There are $3$ bitstrings, so the truthtable has $3$ output bits.\n",
    "\n",
    "The function $f$ represented by the truthtable is promised to be either 1-to-1 or 2-to-1. Our goal is to determine which. For the case of 2-to-1, we also need to compute the mask $\\mathbf{s}$, which satisfies $\\forall \\mathbf{x},\\mathbf{y}$: $\\mathbf{x} \\oplus \\mathbf{y} = \\mathbf{s}$ iff $f(\\mathbf{x}) = f(\\mathbf{y})$. Apparently, if $f$ is 1-to-1, the corresponding mask $\\mathbf{s} = \\mathbf{0}$.\n",
    "\n",
    "Let us first compute the groundtruth mask $\\mathbf{s}$ classically:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The groundtruth mask is 011.\n"
     ]
    }
   ],
   "source": [
    "def compute_mask(input_bitmaps):\n",
    "    vals = list(zip(*input_bitmaps))[::-1]\n",
    "    def find_pair():\n",
    "        for i in range(len(vals)):\n",
    "            for j in range(i + 1, len(vals)):\n",
    "                if vals[i] == vals[j]:\n",
    "                    return i, j\n",
    "        return 0, 0\n",
    "\n",
    "    k1, k2 = find_pair()\n",
    "    return np.binary_repr(k1 ^ k2, int(np.log2(len(input_bitmaps[0]))))\n",
    "\n",
    "mask = compute_mask(bitmaps)\n",
    "print(f'The groundtruth mask is {mask}.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The mask computed using Simon is 011.\n"
     ]
    }
   ],
   "source": [
    "simon = Simon(oracle)\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "result = simon.run(QuantumInstance(backend, shots=1024))\n",
    "print(f'The mask computed using Simon is {result[\"result\"]}.')\n",
    "assert(result['result'] == mask)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also quickly try a truthtable that represents a 1-to-1 function (i.e., the corresponding mask is $\\mathbf{0}$), as follows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The groundtruth mask is 000.\n",
      "The mask computed using Simon is 000.\n"
     ]
    }
   ],
   "source": [
    "bitmaps = [\n",
    "    '00011110', \n",
    "    '01100110', \n",
    "    '10101010'\n",
    "]\n",
    "mask = compute_mask(bitmaps)\n",
    "print(f'The groundtruth mask is {mask}.')\n",
    "\n",
    "oracle = TruthTableOracle(bitmaps)\n",
    "simon = Simon(oracle)\n",
    "result = simon.run(QuantumInstance(backend, shots=1024))\n",
    "print(f'The mask computed using Simon is {result[\"result\"]}.')\n",
    "assert(result['result'] == mask)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Shor's Factoring algorithm\n",
    "\n",
    "[Shor’s Factoring algorithm](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.Shor.html) is one of the most well-known quantum algorithms and finds the prime factors for input integer $N$ in polynomial time. The algorithm implementation in Qiskit is simply provided a target integer to be factored and run, as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The list of factors of 15 as computed by the Shor's algorithm is [3, 5].\n"
     ]
    }
   ],
   "source": [
    "N = 15\n",
    "shor = Shor(N)\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "quantum_instance = QuantumInstance(backend, shots=1024)\n",
    "result = shor.run(quantum_instance)\n",
    "print(f\"The list of factors of {N} as computed by the Shor's algorithm is {result['factors'][0]}.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note: this implementation of Shor's algorithm uses $4n + 2$ qubits, where $n$ is the number of bits representing the integer in binary. So in practice, for now, this implementation is restricted to factorizing small integers. Given the above value of N we compute $4n +2$ below and confirm the size from the actual circuit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Computed of qubits for circuit: 18\n",
      "Actual number of qubits of circuit: 18\n"
     ]
    }
   ],
   "source": [
    "print(f'Computed of qubits for circuit: {4 * math.ceil(math.log(N, 2)) + 2}')\n",
    "print(f'Actual number of qubits of circuit: {shor.construct_circuit().num_qubits}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<h3>Version Information</h3><table><tr><th>Qiskit Software</th><th>Version</th></tr><tr><td>Qiskit</td><td>0.23.0</td></tr><tr><td>Terra</td><td>0.16.0</td></tr><tr><td>Aer</td><td>0.7.0</td></tr><tr><td>Ignis</td><td>0.5.0</td></tr><tr><td>Aqua</td><td>0.8.0</td></tr><tr><td>IBM Q Provider</td><td>0.11.0</td></tr><tr><th>System information</th></tr><tr><td>Python</td><td>3.6.1 |Continuum Analytics, Inc.| (default, May 11 2017, 13:09:58) \n",
       "[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]</td></tr><tr><td>OS</td><td>Linux</td></tr><tr><td>CPUs</td><td>1</td></tr><tr><td>Memory (Gb)</td><td>5.827335357666016</td></tr><tr><td colspan='2'>Sun Nov 08 16:49:50 2020 EST</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style='width: 100%; background-color:#d5d9e0;padding-left: 10px; padding-bottom: 10px; padding-right: 10px; padding-top: 5px'><h3>This code is a part of Qiskit</h3><p>&copy; Copyright IBM 2017, 2020.</p><p>This code is licensed under the Apache License, Version 2.0. You may<br>obtain a copy of this license in the LICENSE.txt file in the root directory<br> of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.<p>Any modifications or derivative works of this code must retain this<br>copyright notice, and modified files need to carry a notice indicating<br>that they have been altered from the originals.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import qiskit.tools.jupyter\n",
    "%qiskit_version_table\n",
    "%qiskit_copyright"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
